package com.fz.song.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.session.HttpSessionEventPublisher;

@Configuration
public class SecurityConfig {

    /**
     * 注册一个密码加密工具
     *
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 实际运行之后貌似没有问题，当建立新会话时，确实被阻止了，如图6-4所示。 如果此时庆幸Spring Security的会话并发控制如此简单，那未免高兴得过早。怎么回事呢？我们首 先尝试将已登录的旧会话注销（通常是访问/logout），理论上应该可以继续登录了，但很遗憾，Spring Security依然提示我们超过了最大会话数。事实上，除非重启服务，否则该用户将很难再次登录系统。 这是因为Spring Security是通过监听session的销毁事件来触发会话信息表相关清理工作的，但我们并没
     * 有注册过相关的监听器，导致Spring Security无法正常清理过期或已注销的会话。
     * 在Servlet中，监听session相关事件的方法是实现HttpSessionListener接口，并在系统中注册该监听 器。Spring Security在HttpSessionEventPublisher类中实现HttpSessionEventPublisher接口，并转化成 Spring的事件机制。
     *
     * 这个问题在新会话剔除旧会话的策略中就已存在，只是没有明显暴露出来，因此只要我们使用会 话管理功能，就应该同时配置HttpSessionEventPublisher。
     * 在Spring事件机制中，事件的发布、订阅都交由Spring容器来托管，我们可以很方便地通过注册 bean的方式来订阅关心的事件。
     * 显然，前面的配置无法正常工作是因为缺少了事件源（会话清理订阅的Spring事件，而非原生的 HttpSessionEvent），另外，还需要把HttpSessionEventPublisher注册到IoC容器中，才能将Java事件转 化成Spring事件
     * @return
     */
    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher() {
        return new HttpSessionEventPublisher();
    }



}
